/*
* 执行最后文件的输出
*/
const fs = require('fs');
const path = require('path');
const { getAST, getDependencies, transform } = require('./parser');//解析与转化
var UglifyJS = require("uglify-js");//js压缩


module.exports = class Compiler {

    constructor(options) {
        const { entry, output } = options;
        this.entry = entry;
        this.output = output;
        this.modules = [];//定义this.modules来填充依赖
    }

    run() {
        // 构建主入口模块
        const entryModule = this.build(this.entry, true);
        // 添加依赖模块
        this.modules.push(entryModule);
        // 遍历递归添加依赖
        this.modules.forEach(_module_ => {
            _module_.dependencies.forEach(dependency => {
                this.modules.push(this.build(dependency));
            });
        });
        // console.log(this.modules);
        this.outFiles();
    }

    // 构建模块
    build(filename, isEntry) {
        let ast;
        if (isEntry) {
            ast = getAST(filename);
            filename = path.basename(filename);
        } else {
            const absolutePath = path.join(process.cwd(), './src', filename + '.js');
            ast = getAST(absolutePath);
        }
        return {
            filename,
            dependencies: getDependencies(ast),
            source: transform(ast),
        };
    }

    // 输出文件
    outFiles() {
        let outputPath = path.join(this.output.path, this.output.filename);
        let modules = '';
        this.modules.forEach(_module => {
            modules += `'${_module.filename}': function(require,module,exports){${_module.source}},`;
        });
        // 加载时自动执行
        const bundle = `(function(modules){
        function require(filename){
            var fn = modules[filename];
            var module = { exports: {}};
            fn(require, module, module.exports)
            return module.exports;
        }
        require('${path.basename(this.entry)}')
    })({${modules}})`;
        if (!fs.existsSync(this.output.path)) fs.mkdirSync(this.output.path);

        fs.writeFileSync(outputPath, bundle, 'utf-8');
        outputPath = path.join(this.output.path, this.output.minimize);
        fs.writeFileSync(outputPath, this.compress(bundle), 'utf-8');
    }
    //压缩
    compress(bundle) {
        return UglifyJS.minify(bundle, { mangle: {   eval: true, } }).code;
    }
};
